package com.max.common.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HttpsURLConnection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONObject;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;


/**
 * 
 * 项目名称:max-project-graphics
 * 文件名称:HttpTool.java
 * 文件描述:
 * 创建人员:chenyibo
 * 创建时间:2013-1-28 下午05:31:10
 * 修改人员:chenyibo
 * 修改时间:2013-1-28 下午05:31:10
 * 修改备注:
 * @version V1.0
 */
public class HttpTool 
{

	private static Log log = LogFactory.getLog("debug");
	
	
	/**建立连接超时时间*/
	private int connectTimeout = 5000;
	
	/**读超时时间*/
	private int readTimeout = 5000;
	
	/**编码方式*/
	private String charset = "UTF-8";
	
	
	public HttpTool() 
	{
		this(2000, 2000, "UTF-8");
	}
	
	
	public HttpTool(int connectTimeout, int readTimeout, String charset) 
	{
		this.connectTimeout = connectTimeout;
		this.readTimeout = readTimeout;
		this.charset = charset;
	}
	

	/**
	 * GET请求指定URL
	 * @param url
	 * @return
	 */
	public Response request(String url)
	{
		return request(url, null);
	}
	
	
	/**
	 * 
	 * @param url
	 * @param bodyParams
	 * @return
	 */
	public Response request(String url, Map<String,String> bodyParams)
	{
		return request(null, url, bodyParams);
	}
	
	
	/**
	 * 
	 * @param url
	 * @param headerParams
	 * @param bodyParams
	 * @return
	 */
	public Response request(String url, Map<String,String> headerParams, 
			Map<String,String> bodyParams)
	{
		return request(null, url, headerParams, bodyParams);
	}
	
	
	/**
	 * 
	 * @param method
	 * @param url
	 * @param bodyParams
	 * @return
	 */
	public Response request(String method, String url, 
			Map<String,String> bodyParams)
	{
		return request(method, url, null, bodyParams);
	}
	
	
	/**
	 * 
	 * @param method
	 * @param url
	 * @param headerParams
	 * @param bodyParams
	 * @return
	 */
	public Response request(String method, String url, 
			Map<String,String> headerParams, Map<String,String> bodyParams)
	{
		byte[] content = null;
		StringBuffer sb = null;
		
		if(bodyParams != null && !bodyParams.isEmpty())
		{
			sb = new StringBuffer();
			
			for(String key:bodyParams.keySet())
			{
				try
				{
					sb.append(URLEncoder.encode(key,charset))
	      		      .append("=")
	      		      .append(bodyParams.get(key)==null?null:URLEncoder.encode(bodyParams.get(key),charset))
	      		      .append("&");
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
			}
			
			sb.deleteCharAt(sb.length()-1);
		}
		
		if(method == null || method.trim().equals("")
				|| method.equalsIgnoreCase("GET"))
		{
			method = "GET";
			
			if(url.indexOf("?") < 0)
				url += "?";
			
			if(!url.endsWith("?"))
				url+="&";
			
			if(sb != null)
				url += sb.toString();
		}
		else
		{
			method = "POST";
			
			if(sb != null)
				content = sb.toString().getBytes();
		}
			
		return request(method, url, headerParams, content);
	}
	
	
	/**
	 * 
	 * @param method
	 * @param url
	 * @param headerParams
	 * @param content
	 * @return
	 * @throws Exception
	 */
	public Response request(String method, String url, 
			Map<String,String> headerParams, byte[] content)
	{
		Response res = null;
		
		HttpURLConnection conn = null;
		OutputStream os = null;
		
		if(method == null || method.trim().equals("")
				|| method.equalsIgnoreCase("GET"))
			method = "GET";
		else
			method = "POST";
		
		try
		{
//			conn = (HttpURLConnection)new URL(url).openConnection();
//			conn.setRequestMethod(method);
//			conn.setConnectTimeout(connectTimeout);
//			conn.setReadTimeout(readTimeout);
//			conn.setDoInput(true);
//			conn.setDoOutput(true);
			log.debug(method+":"+url);
			conn = getHttpURLConnection(url, method, connectTimeout, readTimeout);
			
			if(headerParams != null && !headerParams.isEmpty())
	        {
	        	for(String key:headerParams.keySet())
	        		conn.addRequestProperty(key, headerParams.get(key));
	        }
			
			if(content != null && content.length > 0)
			{
				os = conn.getOutputStream();
	        	os.write(content);
	        	os.flush();
	        	os.close();
			}
			
			res = new Response(conn);
			log.debug("RES:"+res.asString());
		}
		catch(Exception e)
		{
			e.printStackTrace();
			res = new Response(-1,e.getMessage());
		}
		
		return res;
	}
	
	
	public HttpURLConnection getHttpURLConnection(String host, String method, 
			int connectTimeout, int readTimeout) throws Exception
	{
		HttpURLConnection conn = null;
		
		if(host.startsWith("https"))
			conn = (HttpsURLConnection)new URL(host).openConnection();
		else 
			conn = (HttpURLConnection)new URL(host).openConnection();
		
		conn.setRequestMethod(method);
		conn.setConnectTimeout(connectTimeout);
		conn.setReadTimeout(readTimeout);
		conn.setDoInput(true);
		conn.setDoOutput(true);
		
		return conn;
	}
	
	
	public class Response 
	{
		
		/**状态码*/
		private int responseCode = 200;
		
		/**提示消息*/
		private String responseMessage = "success!";
		
		/**编码方式*/
		private String charset = "UTF-8";
		
		private HttpURLConnection conn;
		
		private String responseString = null;

		
		public Response(HttpURLConnection conn) throws Exception 
		{
			this(conn, "UTF-8");
		}

		public Response(HttpURLConnection conn, String charset) throws Exception 
		{
			this.conn = conn;
			this.responseCode = conn.getResponseCode();
			this.responseMessage = conn.getResponseMessage();
			this.charset = charset;
		}
		
		public Response(int responseCode, String responseMessage) 
		{
			super();
			this.responseCode = responseCode;
			this.responseMessage = responseMessage;
		}


		public int getResponseCode() 
		{
			return responseCode;
		}

		public String getResponseMessage() 
		{
			return responseMessage;
		}
		
		public String getURL()
		{
			return conn==null?null:conn.getURL().toString();
		}


		
		/**===================================================================================================*/
		public InputStream asStream() throws Exception
		{
			InputStream is = null;
			
			if(null == (is = conn.getErrorStream()))
	            is = conn.getInputStream();
	        
	        if (null != is && "gzip".equals(conn.getContentEncoding())) 
	            is = new GZIPInputStream(is);
	        
	        return is;
		}
		
		
		public String asString() throws Exception
		{
			if(responseString == null)
			{
				BufferedReader reader = new BufferedReader(new InputStreamReader(asStream(),charset));
				StringBuffer sb = new StringBuffer();
			    String line = null;
			    
			    while((line = reader.readLine()) != null)
			    	sb.append(line).append(System.getProperty("line.separator"));
			    
			    responseString = sb.toString();
			}
			
			StringBuffer sb = new StringBuffer()
				.append("Response.asString:")
				.append(System.getProperty("line.separator"))
				.append(responseString);
			
		    return responseString;
		}
		
		
		public Map<String,String> asParamMap() throws Exception
		{
			Map<String,String> paramMap = new HashMap<String,String>();
			
			String content = asString();
	        String[] array = content.split("&");
	        
	        for(int i = 0; i < array.length; i++)
		    {
		    	String[] a = array[i].split("=");
		    	
		    	if(a.length == 2)
//		    		paramMap.put(URLDecoder.decode(a[0],charset), URLDecoder.decode(a[1],charset));
		    		paramMap.put(a[0].trim(), a[1].trim());
		    }
	        
	        return paramMap;
		}
		
		
		
		public JSONObject asJSONObject() throws Exception
		{
			JSONObject json = new JSONObject(asString());
			
			return json;
		}
		
		
		public JSONArray asJSONArray() throws Exception
		{
			JSONArray array = new JSONArray(asString());
			
			return array;
		}
		

		public Document asDocument() throws Exception
		{
			Document doc = null;
			
			StringReader sr = new StringReader(asString());
			DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = builderFactory.newDocumentBuilder();
			doc = builder.parse(new InputSource(sr));
			
			return doc;
		}
		
		
		public void destroy()
		{
			if(conn != null)
				conn.disconnect();
		}
	}
	
		
	public static void main(String[] args) throws Exception
	{
		HttpTool tool = new HttpTool();
		Response response = tool.request("http://qq.com/");
		
		if(response.getResponseCode() == 200)
			System.out.println(response.asString());
	}
}
